import uvicorn
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from package.fastapi.extend import mount_local_static

from setting import setting


def create_app():
    """创建fastapi对象"""
    kwargs = {}
    if getattr(setting, 'prod', True) is True:  # 正式环境关闭swagger文档
        kwargs = dict(title='Myli', contact={'user': 'miaoyun@miaoyun.io'},
                      swagger_ui_parameters={"defaultModelsExpandDepth": 1}, docs_url=None, redoc_url=None)
    fast_app = FastAPI(**kwargs)
    return fast_app


def register_router(fast_app):
    prefix = '/api/v1'
    from package.fastapi import heartbeat
    fast_app.include_router(heartbeat.router_heartbeat)

    from router_devops import devops, relationship
    fast_app.include_router(devops.router_devops, prefix=prefix)
    fast_app.include_router(relationship.router_graph, prefix=prefix)

    from router_analyzer import search, chart, alert
    fast_app.include_router(search.router_search, prefix=prefix)
    fast_app.include_router(chart.router_chart, prefix=prefix)
    fast_app.include_router(alert.router_alert, prefix=prefix)

    from router_collector import source, agent, transform, model
    fast_app.include_router(source.router_source, prefix=prefix)
    fast_app.include_router(agent.router_agent, prefix=prefix)
    fast_app.include_router(transform.router_transform, prefix=prefix)
    fast_app.include_router(model.router_model, prefix=prefix)

    from router import user, configure, auth, lock, notify, journal, enum, file, about

    fast_app.include_router(user.router_owner, prefix=prefix)
    fast_app.include_router(user.router_user, prefix=prefix)
    fast_app.include_router(configure.router_configure, prefix=prefix)
    fast_app.include_router(enum.router_enum, prefix=prefix)

    fast_app.include_router(auth.router_auth, prefix=prefix)
    fast_app.include_router(auth.router_apikey, prefix=prefix)
    fast_app.include_router(auth.router_oidc, prefix=prefix)

    fast_app.include_router(lock.router_lock, prefix=prefix)
    fast_app.include_router(notify.router_notify, prefix=prefix)
    fast_app.include_router(journal.router_journal, prefix=prefix)

    fast_app.include_router(file.router_directory, prefix=prefix)
    fast_app.include_router(file.router_file, prefix=prefix)

    fast_app.include_router(about.router_about)



def register_auth():
    """
    认证添加
    """
    from fastapi.security import OAuth2PasswordBearer
    from package.fastapi.auth import auth
    auth.init(oauth2_scheme=OAuth2PasswordBearer(tokenUrl=setting.token_url, auto_error=False))


def register_middle():
    """中间件注册"""
    from package.connector.sql_db import db
    from package.connector.redis_db import rdb
    from package.connector.elastic_db import es_db
    from package.connector.kafka_db import kafka_producer
    from package.fastapi.logger import auditor_logger
    from package.fastapi.job import scheduler_job
    from package.connector.neo4j_db import neo4j_db

    neo4j_db.init(host="192.168.101.79", port=7687, auth=("neo4j", "MY.io2019"))
    db.init(url=setting.pg_uri, pool_pre_ping=True)
    rdb.init(host=setting.redis_host, password=setting.redis_password)
    es_db.init(hosts=setting.elasticsearch_hosts, http_auth=setting.elasticsearch_auth)
    kafka_producer.init(**{'bootstrap.servers': setting.kafka_servers, **setting.kafka_options})
    scheduler_job.init_config(store_configure=dict(host=setting.redis_host, password=setting.redis_password,
                                      jobs_key='collector2:apscheduler',
                                      run_times_key='collector2:apscheduler.runtime'),
                 default_configure={'coalesce': True, 'max_instances': 1}, 
                 is_background=True)
    scheduler_job.scheduler.start(paused=True)  # 停止状态 http请求服务与 task定时任务分开
    auditor_logger.init_config(confluent_kafka=kafka_producer)


def register_middleware(fast_app):
    from package.fastapi import middleware
    from package.fastapi.logger import auditor_logger

    fast_app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"],
                            allow_headers=["*"])

    fast_app.add_exception_handler(RequestValidationError, middleware.validation_exception_handler)
    fast_app.add_exception_handler(HTTPException, middleware.http_exception_handler)
    fast_app.add_middleware(middleware.AuditorMiddleware, auditor=auditor_logger)


register_auth()
app = create_app()
mount_local_static(app)

register_middle()
register_middleware(app)
register_router(app)


if __name__ == '__main__':
    uvicorn.run('main:app', host='0.0.0.0', port=8003, reload=True)
